#pragma once
#include "sock.hpp"
#include <functional>
#include <vector>

using func_t = std::function<void(int)>;

class TcpServer;

class ThreadData
{
public: 
    int _sock;
    TcpServer* _server;
public:
    ThreadData(int sock,TcpServer* server):_sock(sock),_server(server)
    {}

    ~ThreadData()
    {}
};

class TcpServer
{
private:
    int _listenSock;
    Sock _sock;
    std::vector<func_t> _func;

    //线程例程
    static void* threadRoutine(void* args)
    {
        pthread_detach(pthread_self());
        ThreadData* td = static_cast<ThreadData*>(args);
        td->_server->excute(td->_sock);
        close(td->_sock);
        delete td;

        return nullptr;
    }

public:
    TcpServer(const uint16_t& port,const std::string& ip = "0.0.0.0")
    {
        _listenSock = _sock.Socket();
        _sock.Bind(_listenSock,port,ip);
        _sock.Listen(_listenSock);

    }

    void bindServer(func_t func)
    {
        _func.push_back(func);
    }

    void excute(int sock)
    {
        for(auto& f : _func)
        {
            f(sock);
        }
    }

    void start()
    {
        while(true)
        {
            std::string client_ip;
            uint16_t client_port;
            int sock = _sock.Accept(_listenSock,&client_ip,&client_port);
            if(sock == -1) continue;
            logMessage(NORMAL, "create new link success, sock: %d", sock);
            pthread_t tid;
            ThreadData* td = new ThreadData(sock,this);
            pthread_create(&tid,nullptr,threadRoutine,td);
        }
    }
    ~TcpServer()
    {
        if(_listenSock >= 0)
        close(_listenSock);
    }
};
